/* Copyright (C) 2014-2016 Dan Chapman <dpniel@ubuntu.com>

   This file is part of Dekko email client for Ubuntu Devices/

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "PostalServiceWorker.h"
#define QT_NO_KEYWORDS
#include <QDebug>
#include <QDesktopServices>
#include <QProcess>
#include "Notify/Notify.h"
#include "MessagingMenu/Source.h"
#include "app/Utils/Path.h"
#include "configure.cmake.h"

#define APP_DESKTOP_ID "dekko.desktop"
#define DEKKO_ICON "/usr/share/icons/suru/apps/sources/dekko-app.svg"
#define DEKKO_SYMBOLIC_ICON "/usr/share/icons/suru/apps/scalable/dekko-app-symbolic.svg"

namespace {
bool isUnity() {
    return qgetenv("XDG_CURRENT_DESKTOP") == "Unity";
}
}

namespace Dekko
{
namespace Notifications
{

PostalServiceWorker::PostalServiceWorker(QObject *parent) :
    QObject(parent)
{
    if (isUnity()) {
        m_mmApp = new MessagingMenu::Application(this, QStringLiteral(DEKKO_DESKTOP_ID));
        connect(m_mmApp, SIGNAL(msgSourceActivated(QString)), this, SLOT(handleSourceActivated(QString)));
        m_mmApp->registerApplication();
    }
}

void PostalServiceWorker::sendNotification(QSharedPointer<PostalMessage> notification)
{

    qDebug() << "PostalMessage: >> account: " << notification->accountId << "From: " << notification->from << "Subject: " << notification->subject;
    // Notify OSD
    notifySend(notification);
    // Unity Messaging menu
    if (isUnity()) {
        appendToMsgMenu(notification);
    }
    // Play notification sound
    playSound();
}

void PostalServiceWorker::sendErrorNotification(ErrorMessage *errorMsg)
{
    Q_UNUSED(errorMsg);
}

void PostalServiceWorker::clearPersistentMessage(QSharedPointer<PostalMessage> message)
{
    removeMessageFromMenu(message->accountId, QString::number(message->uid));
}

void PostalServiceWorker::removeAllSources()
{
    // Just loop over the message keys to get the list of sources :-)
    QStringList keys = m_messages.keys();
    Q_FOREACH(const QString &src, keys) {
        handleSourceActivated(src);
    }
}

void PostalServiceWorker::handleSourceActivated(const QString &sourceId)
{
    qDebug() << "Source activated!: " << sourceId;
    int i = 0;
    Q_FOREACH(MessagingMenu::Source *source, m_sources) {
        if (source->id() == sourceId) {
            qDebug() << "SourceLabel: " << source->label();
            //            source->setRequiresAttention(false);
            MessagingMenu::Source &src = *source;
            if (m_messages.keys().contains(src.id())) {
                auto msgList = m_messages.value(src.id());
                Q_FOREACH(MessagingMenu::Message *msg, msgList) {
                    m_msgMap.remove(msg->id());
                }
            }
            if (m_mmApp->hasSource(src)) {
                m_mmApp->removeSource(src);
            }
            m_sources.takeAt(i)->deleteLater();
            return;
        }
        i++;
    }
}

void PostalServiceWorker::handleMessageActivated(const QString &msgId)
{
    qDebug() << "Message activated: " << msgId;
    MessagingMenu::Source *src = qobject_cast<MessagingMenu::Source *>(sender());
    Q_ASSERT(src);
    auto msgList = m_messages.value(src->id());
    for (int i = 0; i < msgList.size() - 1; ++i) {
        auto msg = msgList.at(i);
        if (msg->id() == msgId) {
            // TODO: open message
#ifdef CLICK_MODE
            QSharedPointer<PostalMessage> post = m_msgMap.value(msg->id());
            QUrl url;
            url.setScheme(QStringLiteral("dekko"));
            url.setHost(QStringLiteral("notify"));
            url.setPath(QStringLiteral("%1/%2/%3").arg(post->accountId, post->mailbox, QString::number(post->uid)));
            QDesktopServices::openUrl(url);
#endif
            MessagingMenu::Message *m = msgList.takeAt(i);
            m->deleteLater();
        }
    }
}

void PostalServiceWorker::removeMessageFromMenu(const QString &srcId, const QString &msgId)
{
    auto msgList = m_messages.value(srcId);
    for (int i = 0; i < msgList.size() - 1; ++i) {
        auto msg = msgList.at(i);
        if (msg->id() == msgId) {
            msg->remove();
            MessagingMenu::Message *m = msgList.takeAt(i);
            m->deleteLater();
        }
    }
}

void PostalServiceWorker::notifySend(QSharedPointer<PostalMessage> notification)
{
    NotifyService::Notify *msg = new NotifyService::Notify(this);
    msg->init();
    msg->send(notification->from, notification->subject);
    // XXX: Delete later??
}

void PostalServiceWorker::appendToMsgMenu(QSharedPointer<PostalMessage> notification)
{
    MessagingMenu::Source *src = 0;
    Q_FOREACH(MessagingMenu::Source *s , m_sources) {
        if (s->id() == notification->accountId) {
            src = s;
            break;
        }
    }
    if (!src) {
        src = m_mmApp->createMessageSource(notification->accountId,
                                           QStringLiteral("Inbox (%1)").arg(notification->accountDescription),
                                           QString(),
                                           false,
                                           -1);
        src->create();
    }

    connect(src, SIGNAL(menuMessageActivated(QString)), this, SLOT(handleMessageActivated(QString)));
    m_sources.append(src);
    MessagingMenu::Message *mmMsg = src->createMessage(QString::number(notification->uid),
                                                       notification->from,
                                                       QString(),
                                                       notification->subject,
                                                       QDateTime::currentDateTime(),
                                                       QUrl(notification->gravatar));
    if (m_messages.keys().contains(src->id())) {
        QList<MessagingMenu::Message *> list = m_messages.value(src->id());
        list.append(mmMsg);
        m_messages.insert(src->id(), list);
    } else {
        m_messages.insert(src->id(), QList<MessagingMenu::Message *>() << mmMsg);
    }
    // keep a map of messaginmenu item to postal message. We will need it
    // to create the url required to open the message.
    m_msgMap.insert(mmMsg->id(), notification);
}

void PostalServiceWorker::playSound()
{
    QString path = Dekko::soundFilePath(QStringLiteral("bwop.ogg"));
    if (!path.isEmpty()) {
        QProcess::execute(QStringLiteral("paplay"), QStringList() << path);
    }
}

}
}

